
#include <wx/filename.h>

#include "ContactTree.h"

#include "MsnContact.h"
#include "MsnMessenger.h"
#include "MsnSession.h"
#include "ContactManager.h"

#include "MessengerPanel.h"
#include "ContactPanel.h"
#include "SessionPanel.h"
#include "PropertyWindow.h"

#include "MsnDef.h"
#include "Util.h"


int ID_MENU_SEND_MESSAGE = wxNewId();
int ID_MENU_SEND_FILE = wxNewId();

int ID_MENU_INVITE_SESSION = wxNewId();
 
int ID_MENU_VIEW_HISTORY = wxNewId();

int ID_MENU_SET_NICKNAME = wxNewId();
int ID_MENU_CANCEL_NICKNAME = wxNewId();

int ID_MENU_ADD_CONTACT = wxNewId();

int ID_MENU_BLOCK_CONTACT = wxNewId();
int ID_MENU_DELETE_CONTACT = wxNewId();

int ID_MENU_REMOVE_CONTACT_GROUP = wxNewId();

int ID_MENU_MOVE_CONTACT = 10000;

int ID_MENU_ADD_GROUP = wxNewId();
int ID_MENU_RENAME_GROUP = wxNewId();
int ID_MENU_DELETE_GROUP = wxNewId();

BEGIN_EVENT_TABLE(ContactTreeCtrl, wxTreeCtrl)
    EVT_MENU(ID_MENU_SEND_MESSAGE, ContactTreeCtrl::OnSendMessage)
	EVT_MENU(ID_MENU_SEND_FILE, ContactTreeCtrl::OnSendFile)

    EVT_MENU(ID_MENU_VIEW_HISTORY, ContactTreeCtrl::OnViewHistory)

	EVT_MENU(ID_MENU_INVITE_SESSION, ContactTreeCtrl::OnInviteSession)	

    EVT_MENU(ID_MENU_SET_NICKNAME, ContactTreeCtrl::OnRenameContact)
	EVT_MENU(ID_MENU_CANCEL_NICKNAME, ContactTreeCtrl::OnCancelNickname)

	EVT_MENU(ID_MENU_BLOCK_CONTACT, ContactTreeCtrl::OnBlockContact)
	
    EVT_MENU(ID_MENU_DELETE_CONTACT, ContactTreeCtrl::OnDeleteContact)

	EVT_MENU(ID_MENU_REMOVE_CONTACT_GROUP, ContactTreeCtrl::OnRemoveContactFromGroup)
    

    EVT_MENU_RANGE(ID_MENU_MOVE_CONTACT,ID_MENU_MOVE_CONTACT + 100, ContactTreeCtrl::OnMoveContact)

    EVT_MENU(ID_MENU_ADD_GROUP, ContactTreeCtrl::OnAddGroup)
    EVT_MENU(ID_MENU_RENAME_GROUP, ContactTreeCtrl::OnRenameGroup)
    EVT_MENU(ID_MENU_DELETE_GROUP, ContactTreeCtrl::OnRemoveGroup)

    EVT_TREE_ITEM_EXPANDED(wxID_ANY, ContactTreeCtrl::OnGroupOpen)
    EVT_TREE_ITEM_COLLAPSED(wxID_ANY, ContactTreeCtrl::OnGroupClose)

    EVT_TREE_BEGIN_LABEL_EDIT(wxID_ANY, ContactTreeCtrl::OnRenameBegin)
    EVT_TREE_END_LABEL_EDIT(wxID_ANY, ContactTreeCtrl::OnRenameEnd)

    EVT_TREE_BEGIN_DRAG(wxID_ANY, ContactTreeCtrl::OnDragBegin)
    EVT_TREE_END_DRAG(wxID_ANY, ContactTreeCtrl::OnDragEnd)

    EVT_RIGHT_DOWN(ContactTreeCtrl::OnRightClick)
    EVT_LEFT_DOWN(ContactTreeCtrl::OnLeftClick)
    EVT_LEFT_DCLICK(ContactTreeCtrl::OnLeftDClick)

	EVT_MOTION(ContactTreeCtrl::OnMouseMotion)

	//EVT_LEAVE_WINDOW(ContactTreeCtrl::OnMouseLeave)

END_EVENT_TABLE()

IMPLEMENT_DYNAMIC_CLASS(ContactTreeCtrl, wxTreeCtrl)

ContactTreeCtrl::ContactTreeCtrl(wxWindow* parent, MessengerPanel* mp, int id)
     : wxTreeCtrl(parent, id, wxDefaultPosition, wxDefaultSize, 
			wxTR_DEFAULT_STYLE|wxTR_HIDE_ROOT|wxTR_LINES_AT_ROOT|wxTR_EDIT_LABELS),
	 messengerPanel(mp),messenger(mp->messenger)
{
	SetImageList(&MsnDef::ICON_LIST);

    MsnTreeData* data = new MsnTreeData(wxEmptyString,wxEmptyString);
    wxTreeItemId root = AddRoot(wxT("root"), 0, -1, data);

	propertyWindow = NULL;

    //Expand(root);
}

ContactTreeCtrl::~ContactTreeCtrl()
{

}

void ContactTreeCtrl::Clear()
{
	this->DeleteChildren(this->GetRootItem());
}

void ContactTreeCtrl::ClearPropertyWindow()
{
	wxDELETE(propertyWindow);
}

void ContactTreeCtrl::ShowMe(bool shown)
{
	if(shown){
		this->Show();
	}else{
		this->Hide();
		wxDELETE(propertyWindow);
	}
}

void ContactTreeCtrl::LoadContactData()
{
    Clear();

	GroupList& groupList = messenger->GetContactManager()->GetGroupList();
    for(GroupList::iterator it = groupList.begin(); it != groupList.end(); ++it){
       MsnGroup* group = *it;
       this->AddGroupItem(group->GetID(), group->GetName());
    }

    ContactMap& contactMap = messenger->GetContactManager()->GetContactMap();
    for(ContactMap::iterator it = contactMap.begin(); it!= contactMap.end(); ++it){
        MsnContact* contact = it->second;
        if(contact->IsInList(FORWARD) ){
            AddContactItem(contact);
        }
    }
}

void ContactTreeCtrl::SearchContact(const wxString& value)
{
	Clear();

	wxString lowerValue = value.Lower();

	ContactMap& contactMap = messenger->GetContactManager()->GetContactMap();
    for(ContactMap::iterator it = contactMap.begin(); it!= contactMap.end(); ++it){
        MsnContact* contact = it->second;
        
		if(contact->IsInList(FORWARD)){
			if(contact->GetName().Lower().StartsWith(lowerValue) || contact->GetPassport().Lower().StartsWith(lowerValue) || contact->GetNickname().Lower().StartsWith(lowerValue)){
				wxString contactID = contact->GetID();
				wxString label = contact->GetDisplayName();
				this->AddContactItem(contactID, wxEmptyString, label, contact);
			}
		}
    }	

	this->SortChildren(this->GetRootItem());
}


void ContactTreeCtrl::AddGroupItem(const wxString& groupID, const wxString& groupName)
{
    MsnTreeData* data = new MsnTreeData(groupID, groupName);
    wxTreeItemId root = this->GetRootItem();
    this->AppendItem(root, groupName, ICON_GROUP_CLOSE, -1, data);
    this->SortChildren(root);
}

void ContactTreeCtrl::AddContactItem(const wxString& contactID, const wxString& groupID, const wxString& label, MsnContact* contact)
{
	wxTreeItemId treeItem = this->FindContactItem(contactID, groupID);
	if(treeItem.IsOk()){
		return;
	}

    int treeIconIndex = MsnDef::GetStatusIconIndex(contact->GetStatus());

    if(treeIconIndex == -1)
        treeIconIndex = ICON_CONTACT_OFFLINE;

    MsnTreeData* data = new MsnTreeData(contactID, label, groupID, contact);
    wxTreeItemId root = this->GetRootItem();
    if(groupID.IsEmpty()){
        this->AppendItem(root, label, treeIconIndex, -1, data);
        this->SortChildren(root);
        return;
    }

    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId child = this->GetFirstChild(root,cookie);
    while(child.IsOk()){
        MsnTreeData* folder = (MsnTreeData*)this->GetItemData(child);
        if(folder->IsGroup() && groupID.IsSameAs(folder->GetID())){
            this->AppendItem(child, label, treeIconIndex, -1, data);
            this->SortChildren(child);
            this->Refresh();
            return;
        }
        child = this->GetNextChild(root,cookie);
    }
}

void ContactTreeCtrl::AddContactItem(MsnContact* contact)
{
    wxString contactID = contact->GetID();
    wxString label = contact->GetDisplayName();

    wxArrayString groupList = contact->GetGroupList();
    if(groupList.IsEmpty()){
        this->AddContactItem(contactID, wxEmptyString, label, contact);
    }else{
        for(unsigned int i=0; i<groupList.GetCount(); i++){
             this->AddContactItem(contactID, groupList.Item(i), label, contact);
        }
    }
}

//delete all the items of this contact in the tree
void ContactTreeCtrl::DeleteContactItem(const wxString& contactID)
{
    wxTreeItemId item = this->FindContactItem(contactID);

    while(item.IsOk()){
        DEBUG(_T(" deleting contact item....")+contactID);
        this->Delete(item);
        item = this->FindContactItem(contactID);
    }
}

void ContactTreeCtrl::DeleteContactItem(const wxString& contactID, const wxString& groupID)
{
    wxTreeItemId item = this->FindContactItem(contactID, groupID);

    if(item.IsOk()){
        DEBUG(_T(" deleting contact item....")+contactID + _T(" in ")+groupID);
        this->Delete(item);
    }
}

wxTreeItemId ContactTreeCtrl::FindContactItem(const wxString& contactID)
{
    const wxTreeItemId root = this->GetRootItem();
    return FindContactItem(root, contactID);
}

wxTreeItemId ContactTreeCtrl::FindContactItem(const wxTreeItemId& parent, const wxString& contactID)
{
    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId item = this->GetFirstChild(parent,cookie);
    while(item.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
        if(data->IsGroup()){
            item = FindContactItem(item, contactID);
            if(item.IsOk())
                return item;
        }else{
            if( contactID.IsSameAs(data->GetID())){
                return item;
            }
        }

        item = this->GetNextChild(parent,cookie);
    }
    return wxTreeItemId();
}

wxTreeItemId ContactTreeCtrl::FindContactItem(const wxString& contactID, const wxString& groupID)
{
    const wxTreeItemId root = this->GetRootItem();
    return FindContactItem(root, contactID, groupID);
}

wxTreeItemId ContactTreeCtrl::FindContactItem(const wxTreeItemId& parent, const wxString& contactID, const wxString& groupID)
{
    MsnTreeData* parentData = (MsnTreeData*)this->GetItemData(parent);

    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId item = this->GetFirstChild(parent,cookie);
    while(item.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
        if(data->IsGroup()){
            item = FindContactItem(item, contactID, groupID);
            if(item.IsOk())
                return item;
        }else{
            if(groupID.IsSameAs(parentData->GetID()) && contactID.IsSameAs(data->GetID())){
                return item;
            }
        }

        item = this->GetNextChild(parent,cookie);
    }
    return wxTreeItemId();
}

wxTreeItemId ContactTreeCtrl::FindContactItemByPassport(const wxTreeItemId& group, const wxString& passport)
{
    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId item = this->GetFirstChild(group,cookie);
    while(item.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
        if(passport.IsSameAs(data->GetContact()->GetPassport()))
            return item;

        item = this->GetNextChild(group,cookie);
    }
    return wxTreeItemId();
}

void ContactTreeCtrl::UpdateContactItemStatus(const wxString& passport, const wxString& status)
{
    const wxTreeItemId root = this->GetRootItem();
    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId item = this->GetFirstChild(root,cookie);
    while(item.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
		
		if(data == NULL) continue;

        if(data->IsContact()){
            MsnContact* contact = data->GetContact();
            if(passport.IsSameAs(contact->GetPassport())){
                //do not update the alias
                UpdateContactItemStatus(item,status);
            }
        }else{
            wxTreeItemId child = FindContactItemByPassport(item, passport);
            if(child.IsOk()){
                UpdateContactItemStatus(child,status);
            }
        }

        item = this->GetNextChild(root,cookie);
    }
}

void ContactTreeCtrl::UpdateContactItemLabel(const wxString& passport,  const wxString& label)
{
   const wxTreeItemId root = this->GetRootItem();
    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId item = this->GetFirstChild(root,cookie);
    while(item.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);

        if(data->IsContact()){
            MsnContact* contact = data->GetContact();
			bool b = contact->HasNickname();
            if(passport.IsSameAs(contact->GetPassport()) && !contact->HasNickname()){
                this->SetItemText(item, label);
                SortChildren(GetItemParent(item));
            }
        }else{
            wxTreeItemId child = FindContactItemByPassport(item, passport);
            if(child.IsOk()){
                MsnTreeData* childData = (MsnTreeData*)this->GetItemData(child);
                MsnContact* contact = childData->GetContact();
                if(!contact->HasNickname()){
                    this->SetItemText(child, label);
                    SortChildren(GetItemParent(child));
                }
            }
        }

        item = this->GetNextChild(root, cookie);
    }
}

void ContactTreeCtrl::UpdateContactItemStatus(wxTreeItemId& item, const wxString& code)
{
    SetItemImage(item, MsnDef::GetStatusIconIndex(code));

    SortChildren(GetItemParent(item));
}

wxTreeItemId ContactTreeCtrl::FindGroupItemByID(const wxString& groupID)
{
    const wxTreeItemId root = this->GetRootItem();
    wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId child = this->GetFirstChild(root,cookie);
    while(child.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(child);
        if(data->IsGroup() && data->GetID().IsSameAs(groupID)) return child;

        child = this->GetNextChild(root,cookie);
    }
    return wxTreeItemId();
}

void ContactTreeCtrl::DeleteGroupItemByID(const wxString& groupID)
{
     wxTreeItemId group = this->FindGroupItemByID(groupID);
     if(group.IsOk()){
        this->Delete(group);
     }
}

void ContactTreeCtrl::UpdateGroupItem(const wxString& groupID, const wxString& groupName)
{
     wxTreeItemId group = this->FindGroupItemByID(groupID);
     if(group.IsOk()){
        this->SetItemText(group, groupName);
        SortChildren(GetItemParent(group));
     }
}

void ContactTreeCtrl::UpdateGroupItem(const wxString& groupID)
{
    wxTreeItemId group = this->FindGroupItemByID(groupID);
    if(!group.IsOk()){
		return;
	}

	int totalCount = 0;
	int onlineCount = 0;

	wxTreeItemIdValue cookie = (wxTreeItemIdValue)100;
    wxTreeItemId item = this->GetFirstChild(group,cookie);	
	while(item.IsOk()){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
        if(data->IsContact()){
			totalCount++;
			MsnContact* contact = data->GetContact();
			if(contact->IsOnline()){
				onlineCount++;
			}
        }
		item = this->GetNextChild(group, cookie);
	}

	MsnTreeData* groupData = (MsnTreeData*)this->GetItemData(group);
	wxString groupName = groupData->GetLabel();
	groupName << _T(" ( ")<<onlineCount<<_T(" / ")<<totalCount<<_T(" )");

	this->SetItemText(group, groupName);
}

void ContactTreeCtrl::UpdateGroupItemForContact(MsnContact* contact)
{
	wxArrayString groupList = contact->GetGroupList();
	for(unsigned int i=0;i<groupList.GetCount();i++){
		wxString groupID = groupList.Item(i);
		UpdateGroupItem(groupID);
    }	
}


void ContactTreeCtrl::OnRightClick(wxMouseEvent& event)
{
    int flags;
    wxTreeItemId item = HitTest(wxPoint(event.GetX(), event.GetY()), flags);

    if (flags & (wxTREE_HITTEST_ONITEM | wxTREE_HITTEST_ONITEMRIGHT | wxTREE_HITTEST_ONITEMINDENT)){
        SelectItem(item);

        wxMenu menu;
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);

        if(data->IsGroup()){
			menu.Append(ID_MENU_ADD_GROUP, _("Add Group"));
			menu.AppendSeparator();
            menu.Append(ID_MENU_RENAME_GROUP, _("Rename Group"));
            menu.Append(ID_MENU_DELETE_GROUP, _("Delete Group"));
            
			if(GetChildrenCount(item) > 0){
				menu.Enable(ID_MENU_DELETE_GROUP, false);
			}
            
        }else{
			MsnContact* contact = data->GetContact();

			menu.Append(ID_MENU_SEND_MESSAGE, _("Send Message"));
			menu.Append(ID_MENU_SEND_FILE, _("Send File"));
			if(!contact->IsOnline()){
				menu.Enable(ID_MENU_SEND_MESSAGE, false);
				menu.Enable(ID_MENU_SEND_FILE, false);
				
			}

			menu.AppendSeparator();
			menu.Append(ID_MENU_INVITE_SESSION, _("Invite To Current Session"));

			menu.AppendSeparator();	
			menu.Append(ID_MENU_VIEW_HISTORY, _("View Message History"));

			SessionPanel* sessionPanel = messengerPanel->CurrentSessionPanel();
			if(!contact->IsOnline() || 
				sessionPanel == NULL || 
				!sessionPanel->GetSession()->IsAlive() ||
				sessionPanel->GetSession()->HasContact(contact->GetPassport()))
			{
				menu.Enable(ID_MENU_INVITE_SESSION, false);
			}

            menu.AppendSeparator();
            menu.Append(ID_MENU_SET_NICKNAME, _("Set Nickname"));

			if(data->GetContact()->HasNickname()){
				menu.Append(ID_MENU_CANCEL_NICKNAME, _("Cancel Nickname"));
			}
 
            GroupList& groupList = messenger->GetContactManager()->GetGroupList();
            wxString groupID = data->GetParentID();

 /* can't create this menu in stack or it will crash
            if(groupList.size()>0){
                wxMenu* moveMenu = new wxMenu;
                for(unsigned int i = 0; i<groupList.size(); ++i){
                    MsnGroup* group = groupList[i];
                    if(!groupID.IsSameAs(group->GetID())){
                        moveMenu->Append(ID_MENU_MOVE_CONTACT + i, group->GetName());
                     }
                }
                menu.AppendSubMenu(moveMenu, _("Move Contact"));
            }
*/         

			//can not remove from root level group
			if(!groupID.IsEmpty())
				menu.Append(ID_MENU_REMOVE_CONTACT_GROUP, _("Remove From This Group"));

			if(contact->IsInList(BLOCKED)){
				menu.Append(ID_MENU_BLOCK_CONTACT, _("UnBlock Contact"));
			}else{
				menu.Append(ID_MENU_BLOCK_CONTACT, _("Block Contact"));
			}
			
			menu.Append(ID_MENU_DELETE_CONTACT, _("Delete Contact"));      
		}
		
		this->PopupMenu(&menu);
        
    }else{
        event.Skip();
    }
}

void ContactTreeCtrl::OnLeftDClick(wxMouseEvent& event)
{
    int flags;
    wxTreeItemId item = HitTest(wxPoint(event.GetX(), event.GetY()), flags);

    if (flags & (wxTREE_HITTEST_ONITEM )){
        MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);

        if(data->IsContact() &&  data->GetContact()->IsOnline()){
			wxString passport = data->GetContact()->GetPassport();

			messengerPanel->OpenSessionPanel(passport, true);

			/*
			SessionPanel* panel = messengerPanel->FindSessionPanel(passport);
			if(panel == NULL){
				panel = messengerPanel->OpenSessionPanel(passport, true);
			}
			MsnSession* session = messenger->OpenSession(passport);
			panel->AttachSession(session);
			*/
		}else{
            event.Skip();
        }
    }
}

void ContactTreeCtrl::OnLeftClick(wxMouseEvent& event)
{
    int flags;

	wxTreeItemId item = HitTest(wxPoint(event.GetX(), event.GetY()), flags);

	wxDELETE(propertyWindow);

    if (flags & wxTREE_HITTEST_ONITEMICON ){    
		MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
		if(data->IsGroup()){
			return;
		}

			DEBUG(_T("new property window"));
			
			//wxPoint pos = wxGetMousePosition();
			
			wxRect rect;
			GetBoundingRect(item, rect);
			int y = rect.GetY() + rect.GetHeight();
			ClientToScreen(&y, &y);
			int x = wxGetMousePosition().x + rect.GetHeight();

			wxPoint pos(x, y);

			propertyWindow = new PropertyWindow(this, pos, data->GetContact());
			propertyWindow->SetFocus();

    }else
        event.Skip();
}

void ContactTreeCtrl::OnMouseMotion(wxMouseEvent& event)
{
	//DEBUG(_T("mouse move"));
}


void ContactTreeCtrl::CheckMouseMotion()
{
	DEBUG(_T("mouse check"));

	wxPoint pos = ScreenToClient(wxGetMousePosition());
	time_t now = wxDateTime::GetTimeNow();

	if(pos == stuckPosition){
		if(now - stuckTime > 1){
			
			int flags;
			wxTreeItemId item = HitTest(pos, flags);

			if (flags & (wxTREE_HITTEST_ONITEMICON |wxTREE_HITTEST_ONITEMLABEL) ){

				MsnTreeData* data = (MsnTreeData*)this->GetItemData(item);
				if(data->IsGroup()){
					//mouseItem = wxTreeItemId();
					return;
				}

				DEBUG(_T("Show property window"));


				propertyWindow = new PropertyWindow(this, wxGetMousePosition(), data->GetContact());
	
			}
		}
		
	}else{
		stuckTime = now;
		stuckPosition = pos;

		wxDELETE(propertyWindow);
	}	
}

void ContactTreeCtrl::OnAddGroup(wxCommandEvent& event)
{
    wxTextEntryDialog dialog(this, _("Enter the group name"),_T(""),_T(""),wxOK|wxCANCEL);
    if(dialog.ShowModal() == wxID_OK){
        wxString name = dialog.GetValue();
        if(!name.IsEmpty())
            messenger->AddGroup(name);
    }
}

void ContactTreeCtrl::OnSendFile(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->GetContact()->IsOnline()){
		wxString passport = data->GetContact()->GetPassport();
		SessionPanel* panel = messengerPanel->OpenSessionPanel(passport, true);
		wxFileDialog fileDialog(this, _("Select File"), _T(""), _T(""), _T("*.*"), wxFD_OPEN);
		if (fileDialog.ShowModal() == wxID_OK){
			//panel->GetSession()->SendFileInviteMessage(fileDialog.GetPath());
			panel->GetSession()->SendP2PSessionInviteMessage(fileDialog.GetPath());
		}
    }
}

void ContactTreeCtrl::OnSendMessage(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->GetContact()->IsOnline()){
		wxString passport = data->GetContact()->GetPassport();
		messengerPanel->OpenSessionPanel(passport, true);
    }



}

void ContactTreeCtrl::OnViewHistory(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    wxString passport = data->GetContact()->GetPassport();

	wxString filePath = messenger->GetHistoryDirectory() + wxString(wxFileName::GetPathSeparator()) + passport + _T(".log");

	FileUtil::OpenFileWIthDefaultApp(filePath);
}

void ContactTreeCtrl::OnInviteSession(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);	
	MsnContact* contact = data->GetContact();

	if(contact->IsOnline()){
		SessionPanel* sessionPanel = messengerPanel->CurrentSessionPanel();
		MsnSession* session = sessionPanel->GetSession();
		session->InviteContact(contact->GetPassport());
	}
}

void ContactTreeCtrl::OnAddContact(wxCommandEvent& event)
{
	wxTextEntryDialog dialog(this, _("Enter the email:"), _T(""), _T(""), wxOK|wxCANCEL);
    if(dialog.ShowModal() == wxID_OK){
        wxString email = dialog.GetValue();
        if(!email.IsEmpty())
            messenger->AddContact(email, _T("AL"));
			messenger->AddContact(email, _T("FL"));
    }
}

void ContactTreeCtrl::OnMoveContact(wxCommandEvent& event)
{
    int id = event.GetId();

    int index = id - ID_MENU_MOVE_CONTACT;
    // wxMessageBox(s<<index);
	wxString groupID = messenger->GetContactManager()->GetGroupList()[index]->GetID();
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->IsContact()){
        messenger->AddContactToGroup(data->GetID(), groupID);
        if(!data->GetParentID().IsEmpty()){
            messenger->RemoveContact(data->GetID(), data->GetParentID());
        }
    }
}

void ContactTreeCtrl::OnBlockContact(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
	MsnContact* contact = data->GetContact();
	if(contact->IsInList(BLOCKED)){
		messenger->UnBlockContact(contact->GetPassport());
	}else{
		messenger->BlockContact(contact->GetPassport());
	}
}

void ContactTreeCtrl::OnDeleteContact(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->IsContact()){
        messenger->DeleteContact(data->GetContact());
    }
}

void ContactTreeCtrl::OnRemoveContactFromGroup(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->IsContact()){
        messenger->RemoveContact(data->GetID(), data->GetParentID());
    }
}

void ContactTreeCtrl::OnRenameContact(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    this->EditLabel(item);
}

void ContactTreeCtrl::OnCancelNickname(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();
    
	MsnTreeData* data = (MsnTreeData*)GetItemData(item);

	MsnContact* contact = data->GetContact();

	messenger->GetContactManager()->UpdateContactNickname(contact->GetPassport(), wxEmptyString);
	this->SetItemText(item, contact->GetDisplayName());
}

void ContactTreeCtrl::OnRenameGroup(wxCommandEvent& event)
{
    this->EditLabel(GetSelection());
}

void ContactTreeCtrl::OnGroupOpen(wxTreeEvent& event)
{
    wxTreeItemId item = event.GetItem();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->IsGroup()){
        this->SetItemImage(item, ICON_GROUP_OPEN);
    }
}

void ContactTreeCtrl::OnGroupClose(wxTreeEvent& event)
{
    wxTreeItemId item = event.GetItem();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->IsGroup()){
        this->SetItemImage(item, ICON_GROUP_CLOSE);
    }
}

void ContactTreeCtrl::OnRenameBegin(wxTreeEvent& event)
{

}

void ContactTreeCtrl::OnRenameEnd(wxTreeEvent& event)
{
    wxTreeItemId item = event.GetItem();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);

    wxString label = event.GetLabel();

    if(label.IsEmpty() || label.IsSameAs(this->GetItemText(item)))
        return;

    if(data->IsGroup()){
        messenger->RenameGroup(data->GetID(), label);
    }else{
        messenger->GetContactManager()->UpdateContactNickname(data->GetContact()->GetPassport(), label);
        //messenger->ChangeName(_T("tuxitty2"));
        //MsnMessenger::Get()->SetUserName(_T("rrrrrrrr"));
    }
}

void ContactTreeCtrl::OnDragBegin(wxTreeEvent& event)
{
    wxTreeItemId item = event.GetItem();
    MsnTreeData* data = (MsnTreeData*)GetItemData(item);
    if(data->IsContact()){
		dragSrcItem = item;
        event.Allow();
    }
}

void ContactTreeCtrl::OnDragEnd(wxTreeEvent& event)
{
    wxTreeItemId newItem = event.GetItem();

    if(dragSrcItem.IsOk() && newItem.IsOk()){
		MsnTreeData* oldData = (MsnTreeData*)GetItemData(dragSrcItem);
        MsnTreeData* newData = (MsnTreeData*)GetItemData(newItem);

		wxString contactID = oldData->GetID();
		wxString oldGroupID = oldData->GetParentID();
		MsnContact* contact = oldData->GetContact();

		//move to new group
		if(newData->IsGroup() && !newData->GetID().IsSameAs(oldData->GetParentID())){
			wxString newGroupID = newData->GetID();

			//do ui updating first to prevent possible crash caused by user operation
			this->AddContactItem(contactID, newGroupID, contact->GetDisplayName(), contact);
			this->DeleteContactItem(contactID, oldGroupID);
			
			messenger->AddContactToGroup(contactID, newGroupID);
			//if the old item is not in root group, remove the group
			if(!oldGroupID.IsEmpty()){	
				messenger->RemoveContact(contactID, oldGroupID);
			}
		}

		if(newData->IsContact() && !newData->GetParentID().IsSameAs(oldData->GetParentID())){

			wxString newGroupID = newData->GetParentID();

			//do ui updating first to prevent possible crash caused by user operation
			this->AddContactItem(contactID, newGroupID, contact->GetDisplayName(), contact);
			this->DeleteContactItem(contactID, oldGroupID);

			messenger->AddContactToGroup(contactID, newGroupID);
			if(!oldGroupID.IsEmpty()){
				messenger->RemoveContact(contactID, oldGroupID);
			}
		}
    }

	dragSrcItem = wxTreeItemId();
}

void ContactTreeCtrl::OnRemoveGroup(wxCommandEvent& event)
{
    wxTreeItemId item = GetSelection();

	int childCount = GetChildrenCount(item, false);

	if(childCount == 0){
		MsnTreeData* data = (MsnTreeData*)GetItemData(item);
		messenger->DeleteGroup(data->GetID());
	}else{
		wxMessageBox(_("The group is not empty."));
	}
}

int ContactTreeCtrl::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2)
{
    MsnTreeData* data1 = (MsnTreeData*)this->GetItemData(item1);
    MsnTreeData* data2 = (MsnTreeData*)this->GetItemData(item2);

    if(data1->IsContact() && data2->IsGroup()) return -1;
    if(data1->IsGroup() && data2->IsContact()) return 1;

    if(data1->IsContact() && data2->IsContact()){
        if(data1->GetContact()->IsOnline() && !data2->GetContact()->IsOnline()){
            return -1;
        }

        if(!data1->GetContact()->IsOnline() && data2->GetContact()->IsOnline()){
            return 1;
        }
    }

    return this->GetItemText(item1).CmpNoCase(this->GetItemText(item2));
}

